package com.roosterrobotics.replicant.provider;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;

public class ReplicantContentProvider extends ContentProvider {
	
	public static final String AUTHORITY = "com.roosterrobotics.replicant.provider";
	public static final String COMMUNITY = "community";
	private ReplicantDbAdapter db;
	
	private static UriMatcher sUriMatcher;
	private static HashMap <String, String> sReplicantProjectionMap;
	
	private static final int COMMUNITIES = 1;
	private static final int COMMUNITY_ID = 2;
	private static final int DEVICES = 3;
	private static final int DEVICE_ID = 4;
	private static final int DEVICES_BY_COMMUNITY = 5;
	private static final int SENSORS = 6;
	private static final int SENSOR_ID = 7;
	private static final int SENSORS_BY_DEVICE = 8;
	private static final int ACTUATORS = 9;
	private static final int ACTUATOR_ID = 10;
	private static final int ACTUATORS_BY_DEVICE = 11;
	
	static {
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(AUTHORITY, ReplicantData.Communities.COMMUNITY_NAME, COMMUNITIES);
		sUriMatcher.addURI(AUTHORITY, ReplicantData.Communities.COMMUNITY_NAME + "/#", COMMUNITY_ID);
		sUriMatcher.addURI(AUTHORITY, ReplicantData.Devices.DEVICE_NAME, DEVICES);
		sUriMatcher.addURI(AUTHORITY, ReplicantData.Devices.DEVICE_NAME + "/#", DEVICE_ID);
		sUriMatcher.addURI(AUTHORITY, ReplicantData.Devices.DEVICE_NAME + "/" + 
				ReplicantData.Communities.COMMUNITY_NAME + "/#", DEVICES_BY_COMMUNITY);
		sUriMatcher.addURI(AUTHORITY, ReplicantData.Sensors.SENSOR_NAME, SENSORS);
		sUriMatcher.addURI(AUTHORITY, ReplicantData.Sensors.SENSOR_NAME + "/#", SENSOR_ID);
		sUriMatcher.addURI(AUTHORITY, ReplicantData.Sensors.SENSOR_NAME + "/" + 
				ReplicantData.Devices.DEVICE_NAME + "/#", SENSORS_BY_DEVICE);
		sUriMatcher.addURI(AUTHORITY, ReplicantData.Actuators.ACTUATOR_NAME, ACTUATORS);
		sUriMatcher.addURI(AUTHORITY, ReplicantData.Actuators.ACTUATOR_NAME + "/#", ACTUATOR_ID);
		sUriMatcher.addURI(AUTHORITY, ReplicantData.Actuators.ACTUATOR_NAME + "/" + 
				ReplicantData.Devices.DEVICE_NAME + "/#", ACTUATORS_BY_DEVICE);
		
		sReplicantProjectionMap = new HashMap<String,String>();
		sReplicantProjectionMap.put(BaseColumns._ID, BaseColumns._ID);
		sReplicantProjectionMap.put(ReplicantData.Communities.COMMUNITY_NAME_COLUMN_NAME, ReplicantData.Communities.COMMUNITY_NAME_COLUMN_NAME);
		
	}
	
	public ReplicantContentProvider() {

	}
	

	
	@Override
	public boolean onCreate() {
		
		db = new ReplicantDbAdapter(getContext());
		db.open();
		return true;
	}
	
	
	@Override
	public int delete(Uri uri, String arg1, String[] arg2) {
		int match = sUriMatcher.match(uri);
		int affected = 0;
		Long id = ContentUris.parseId(uri);
		switch(match) {
		case COMMUNITY_ID:
			affected = db.deleteCommunity(id);
			return affected;
		case DEVICE_ID:
			affected = db.deleteDevice(id);
			return affected;
		case SENSOR_ID:
			affected = db.deleteSensor(id);
			return affected;
		default:
			throw new IllegalArgumentException("unsupported uri: " + uri);
		}
	}

	@Override
	public String getType(Uri uri) {
		switch (sUriMatcher.match(uri)) {
		case COMMUNITIES:
			return ReplicantData.Communities.CONTENT_TYPE;
		
		case COMMUNITY_ID:
			return ReplicantData.Communities.CONTENT_COMMUNITY_TYPE;
		
		case DEVICES:
			return ReplicantData.Devices.CONTENT_TYPE;
		
		case DEVICE_ID:
			return ReplicantData.Devices.CONTENT_DEVICE_TYPE;
		
		case SENSORS:
			return ReplicantData.Sensors.CONTENT_TYPE;
		
		case SENSOR_ID:
			return ReplicantData.Sensors.CONTENT_SENSOR_TYPE;
		
		case ACTUATORS:
			return ReplicantData.Actuators.CONTENT_TYPE;
		
		case ACTUATOR_ID:
			return ReplicantData.Actuators.CONTENT_ACTUATOR_TYPE;
			
		default:
			throw new IllegalArgumentException("Unknown MIME type: " + uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		int match = sUriMatcher.match(uri);
		Long rowId = (long) 0;
		Uri outUri = null;
		
		switch(match) {
		case COMMUNITIES:
			if (values != null) {
				rowId = db.createCommunity(values.getAsString(ReplicantData.Communities.COMMUNITY_NAME_COLUMN_NAME));
			}
			if (rowId > 0) {
				outUri = ContentUris.withAppendedId(ReplicantData.Communities.CONTENT_URI, rowId);
				getContext().getContentResolver().notifyChange(outUri, null);
			}
			return outUri;
		case DEVICES:
			if (values != null) {
				String name = values.getAsString(ReplicantData.Devices.DEVICE_NAME_COLUMN_NAME);
				String address = values.getAsString(ReplicantData.Devices.DEVICE_ADDRESS_COLUMN_NAME);
				Long commId = values.getAsLong(ReplicantData.Devices.DEVICE_COMMUNITY_COLUMN_NAME);
				Long port = values.getAsLong(ReplicantData.Devices.DEVICE_PORT_COLUMN_NAME);
				boolean lock = values.getAsBoolean(ReplicantData.Devices.DEVICE_LOCK_COLUMN_NAME);
				rowId = db.createDevice(name, commId, address, port, lock);
				if (rowId > 0) {
					outUri = ContentUris.withAppendedId(ReplicantData.Devices.CONTENT_URI, rowId);
					getContext().getContentResolver().notifyChange(outUri, null);

				}
			}
			return outUri;
		case SENSORS:
			if (values != null) {
				String name = values.getAsString(ReplicantData.Sensors.SENSOR_NAME_COLUMN_NAME);
				String units = values.getAsString(ReplicantData.Sensors.SENSOR_UNITS_COLUMN_NAME);
				boolean isDigital = values.getAsBoolean(ReplicantData.Sensors.SENSOR_ISDIGITAL_COLUMN_NAME);
				Long devId = values.getAsLong(ReplicantData.Sensors.SENSOR_DEVICE_COLUMN_NAME);
				Long int_id =  values.getAsLong(ReplicantData.Sensors.SENSOR_INTERNAL_ID_COLUMN_NAME);
				rowId = db.createSensor(name, units, isDigital, devId, int_id);
				if (rowId > 0) {
					outUri = ContentUris.withAppendedId(ReplicantData.Sensors.CONTENT_URI, rowId);
					getContext().getContentResolver().notifyChange(outUri, null);
				}
			}
			return outUri;
		
		case ACTUATORS:
			if (values != null) {
				String name = values.getAsString(ReplicantData.Actuators.ACTUATOR_NAME_COLUMN_NAME);
				Long actId = values.getAsLong(ReplicantData.Actuators.ACTUATOR_ID_COLUMN_NAME);
				Long actMinVal = values.getAsLong(ReplicantData.Actuators.ACTUATOR_MINVALUE);
				Long actMaxVal = values.getAsLong(ReplicantData.Actuators.ACTUATOR_MAXVALUE);
				boolean feedBack = values.getAsBoolean(ReplicantData.Actuators.ACTUATOR_FEEDBACK_COLUMN_NAME);
				Long device = values.getAsLong(ReplicantData.Actuators.ACTUATOR_DEVICE_COLUMN_NAME);
				Long intId = values.getAsLong(ReplicantData.Actuators.ACTUATOR_INTERNAL_ID_COLUMN_NAME);
				rowId = db.createActuator(name, actMinVal, actMaxVal, feedBack, device, intId);
				if (rowId > 0) {
					outUri = ContentUris.withAppendedId(ReplicantData.Actuators.CONTENT_URI, rowId);
					getContext().getContentResolver().notifyChange(outUri, null);
				}
			}
			return outUri;
		default:
			throw new IllegalArgumentException("unsupported uri: " + uri);
		}
	}



	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {

		int match = sUriMatcher.match(uri);
		Cursor c;
		
		switch(match) {
		case COMMUNITIES:
			c = db.fetchAllCommunities();
			c.setNotificationUri(getContext().getContentResolver(), ReplicantData.Communities.CONTENT_URI);
			break;
		case COMMUNITY_ID:
			long commId = ContentUris.parseId(uri);
			c = db.fetchCommunity(commId);
			c.setNotificationUri(getContext().getContentResolver(), ReplicantData.Communities.CONTENT_URI);
			break;
		case DEVICES:
			c = db.fetchAllDevices();
			c.setNotificationUri(getContext().getContentResolver(), ReplicantData.Devices.CONTENT_URI);
			break;
		case DEVICE_ID:
			long devId = ContentUris.parseId(uri);
			c = db.fetchDevice(devId);
			c.setNotificationUri(getContext().getContentResolver(), ReplicantData.Devices.CONTENT_URI);
			break;
		case DEVICES_BY_COMMUNITY:
			long commFkId = ContentUris.parseId(uri);
			c = db.fetchDevicesByCommunity(commFkId);
			c.setNotificationUri(getContext().getContentResolver(), ReplicantData.Devices.CONTENT_URI);
			break;
		case SENSOR_ID:
			long sensId = ContentUris.parseId(uri);
			c = db.fetchSensor(sensId);
			c.setNotificationUri(getContext().getContentResolver(), ReplicantData.Sensors.CONTENT_URI);
			break;
		case SENSORS_BY_DEVICE:
			long devId1 = ContentUris.parseId(uri);
			c = db.fetchSensorByDevice(devId1);
			c.setNotificationUri(getContext().getContentResolver(), ReplicantData.Sensors.CONTENT_URI);
			break;
		case ACTUATOR_ID:
			long actId = ContentUris.parseId(uri);
			c = db.fetchActuatorByDevice(actId);
			c.setNotificationUri(getContext().getContentResolver(), ReplicantData.Actuators.CONTENT_URI);
			break;
		case ACTUATORS_BY_DEVICE:
			long actId1 = ContentUris.parseId(uri);
			c = db.fetchActuatorByDevice(actId1);
			c.setNotificationUri(getContext().getContentResolver(), ReplicantData.Actuators.CONTENT_URI);
			break;
		default:
			throw new IllegalArgumentException("unsupported uri: " + uri);
		}
			
		
		return c;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		
		getContext().getContentResolver().notifyChange(uri, null);
		int match = sUriMatcher.match(uri);
		int affected = 0;
		
		switch(match) {
		case COMMUNITY_ID:
			long commId = values.getAsLong(ReplicantData.Communities.COMMUNITY_ID_COLUMN_NAME);
			String name = values.getAsString(ReplicantData.Communities.COMMUNITY_NAME_COLUMN_NAME);
			
			affected = db.updateCommunity(commId, name);
			break;
		case DEVICE_ID:
			long devId = values.getAsLong(ReplicantData.Devices.DEVICE_ID_COLUMN_NAME);
			long commId1 = values.getAsLong(ReplicantData.Devices.DEVICE_COMMUNITY_COLUMN_NAME);
			String name1 = values.getAsString(ReplicantData.Devices.DEVICE_NAME_COLUMN_NAME);
			String address = values.getAsString(ReplicantData.Devices.DEVICE_ADDRESS_COLUMN_NAME);
			long port = values.getAsLong(ReplicantData.Devices.DEVICE_PORT_COLUMN_NAME);
			boolean lock = values.getAsBoolean(ReplicantData.Devices.DEVICE_LOCK_COLUMN_NAME);
			boolean replicant = values.getAsBoolean(ReplicantData.Devices.DEVICE_REPLICANT_COLUMN_NAME);
			affected = db.updateDevice(devId, name1, address, port, lock, replicant, commId1);
			break;
		default:
			throw new IllegalArgumentException("unsupported uri: " + uri);
		}
		getContext().getContentResolver().notifyChange(uri, null);
		return affected;		
	}

}
